package com.itheima.stock.service.impl;

import com.alibaba.excel.EasyExcel;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.itheima.stock.common.StockInfoConfig;
import com.itheima.stock.common.domain.InnerBlockDomain;
import com.itheima.stock.common.domain.InnerMarketDomian;
import com.itheima.stock.common.domain.InnerRtDomain;
import com.itheima.stock.common.domain.InnerRtTimeDomian;
import com.itheima.stock.mapper.StockBlockRtInfoMapper;
import com.itheima.stock.mapper.StockBusinessMapper;
import com.itheima.stock.mapper.StockMarketIndexInfoMapper;
import com.itheima.stock.mapper.StockRtInfoMapper;
import com.itheima.stock.pojo.StockBusiness;
import com.itheima.stock.service.StockService;
import com.itheima.stock.utils.DateTimeUtil;
import com.itheima.stock.vo.resp.PageResult;
import com.itheima.stock.vo.resp.R;
import com.itheima.stock.vo.resp.ResponseCode;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class StockServiceImpl implements StockService {
    @Autowired
    private StockBusinessMapper stockBusinessMapper;
    @Autowired
    private StockInfoConfig stockInfoConfig;
    @Autowired
    private StockMarketIndexInfoMapper stockMarketIndexInfoMapper;
    @Autowired
    private StockBlockRtInfoMapper stockBlockRtInfoMapper;
    @Autowired
    private StockRtInfoMapper stockRtInfoMapper;


    @Override
    public R<List<StockBusiness>> findAllBusiness() {
        List<StockBusiness> list = stockBusinessMapper.findAll();
        if (CollectionUtils.isEmpty(list)) {
            R.error(ResponseCode.NO_RESPONSE_DATA.getMessage());
        }
        return R.ok(list);
    }

    /**
     * 需求说明: 沪深两市板块分时行情数据查询，以交易时间和交易总金额降序查询，取前10条数据
     *
     * @return
     */
    @Override
    public R<List<InnerMarketDomian>> getInnerMarketDomain() {
        //1.获取国内大盘的id集合
        List<String> innerIds = stockInfoConfig.getInner();
        //2.获取最近最新的股票有效交易日
        String lastDate = DateTimeUtil.getLastDateString4Stock(DateTime.now());
        lastDate = "20211226105600";//TODO 后面实时数据后删掉
        //3.调用mapper查询指定日期下对应的国内大盘数据
        List<InnerMarketDomian> innerMarketDomians = stockMarketIndexInfoMapper.selectByIdsAndDate(innerIds, lastDate);
        //组装响应的额数据
        if (CollectionUtils.isEmpty(innerMarketDomians)) {
            return R.error(ResponseCode.NO_RESPONSE_DATA.getMessage());
        }
        return R.ok(innerMarketDomians);
    }

    /**
     * 需求说明: 沪深两市板块分时行情数据查询，以交易时间和交易总金额降序查询，取前10条数据
     *
     * @return
     */
    @Override
    public R<List<InnerBlockDomain>> getInnerBlockDomain() {
        //1.调用mapper接口获取数据
        List<InnerBlockDomain> infos = stockBlockRtInfoMapper.sectorAllLimit();
        //2.组装数据
        if (CollectionUtils.isEmpty(infos)) {
            return R.error(ResponseCode.NO_RESPONSE_DATA.getMessage());
        }
        return R.ok(infos);
    }

    /**
     * 功能描述：沪深两市个股涨幅分时行情数据查询，以时间顺序和涨幅查询前10条数据
     *
     * @return
     */
    @Override
    public R<List<InnerRtDomain>> getInnerRtDomain() {
        List<InnerRtDomain> list = stockRtInfoMapper.getInnerRtDomain();
        if (CollectionUtils.isEmpty(list)) {
            return R.error(ResponseCode.NO_RESPONSE_DATA.getMessage());
        }
        return R.ok(list);
    }

    /**
     * 沪深两市个股行情列表查询 ,以时间顺序和涨幅排序分页查询
     *
     * @param page     当前页
     * @param pageSize 每页条数
     * @return 响应给前端数据
     */
    @Override
    public R<PageResult<InnerRtDomain>> getStockAll(Integer page, Integer pageSize) {
        //1.设置分页参数
        PageHelper.startPage(page, pageSize);
        //2.通过mapper查询
        List<InnerRtDomain> infos = stockRtInfoMapper.getStockAll();
        //3.封装到PageResult下
        //3.1 封装PageInfo对象
        PageInfo<InnerRtDomain> listPageInfos = new PageInfo<>(infos);
        //3.2 将PageInfo转PageResult
        PageResult<InnerRtDomain> pageResult = new PageResult<>(listPageInfos);
        //4.封装R响应对象
        return R.ok(pageResult);
    }

    /**
     * 功能描述：沪深两市涨跌停分时行情数据查询，查询T日每分钟的涨跌停数据（T：当前股票交易日）
     * 查询每分钟的涨停和跌停的数据的同级；
     * 如果不在股票的交易日内，那么就统计最近的股票交易下的数据
     * map:
     * upList:涨停数据统计
     * downList:跌停数据统计
     *
     * @return
     */
    @Override
    public R<Map> getStockUpdownCount() {
        //1.获取股票最近的有效交易日期,精确到秒
        String avlDate = DateTimeUtil.getLastDateString4Stock(DateTime.now());
        avlDate = "20220106092500";
        //2.统计涨停的数据 约定：1代表涨停 0：跌停
        List<Map> upCount = stockRtInfoMapper.getStockUpdownCount(avlDate, 1);
        //3.统计跌停的数据
        List<Map> downCount = stockRtInfoMapper.getStockUpdownCount(avlDate, 0);
        //4.组装数据到map
        HashMap<String, List<Map>> map = new HashMap<>();
        map.put("upList", upCount);
        map.put("downList", downCount);
        //5.响应
        return R.ok(map);
    }

    /**
     * 涨幅榜数据分页导出到excel
     *
     * @param response 用于响应excel文件
     * @param page     当前页
     * @param pageSize 每页大小
     */
    @Override
    public void getExport(HttpServletResponse response, Integer page, Integer pageSize) {
        try {
            //1.设置响应数据的类型:excel
            response.setContentType("application/vnd.ms-excel");
            //2.设置响应数据的编码格式
            response.setCharacterEncoding("utf-8");
            //3.设置默认的文件名称
            // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
            String fileName = URLEncoder.encode("stocket", "utf-8");
            //设置默认文件名称
            response.setHeader("content-disposition", "attachment;filename=" + fileName + ".xlsx");
            //获取导出的分页数据
            PageHelper.startPage(page, pageSize);
            List<InnerRtDomain> stockAll = stockRtInfoMapper.getStockAll();
            EasyExcel.write(response.getOutputStream(), InnerRtDomain.class)
                    .sheet("stockRt").doWrite(stockAll);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 沪深两市个股涨跌行情数据查询，查询T日分时成交量与T-1日分时成交量对比数据
     * 简言之，统计T日和T-1日沪深两市每分钟的成交量的对比数据；
     *
     * @return 返回数据格式：
     * {
     * "code": 1,
     * "data": {
     * "volList": [{ "count": 3926392,"time": "202112310930"},......],
     * "yesVolList":[{"count": 3926392,"time": "202112310930"},......]
     * }
     * }
     */
    @Override
    public R<Map> getStockTradevol() {
        //1.获取最近的股票交易日时间，精确到秒 T交易日
        DateTime tDate = DateTimeUtil.getLastDate4Stock(DateTime.now());
        //转为字符串
        String tStr = DateTimeUtil.parseToString4Stock(tDate);
        //TODO 后续注释掉
        tStr = "2022-01-03 14:30:00";
        //2.获取T-1日精确到秒
        DateTime preTDate = DateTimeUtil.getPreviousTradingDay(tDate);
        //转为字符串
        String preTStr = DateTimeUtil.parseToString4Stock(preTDate);
        //TODO 后续注释掉
        preTStr = "2022-01-02 14:30:00";
        //获取A股编号
        List<String> inner = stockInfoConfig.getInner();
        //3.1 T交易日
        List<Map> tData = stockMarketIndexInfoMapper.getStockTradevol(inner, tStr);
        //3.2 T-1交易日
        List<Map> preTData = stockMarketIndexInfoMapper.getStockTradevol(inner, preTStr);
        //响应数据
        HashMap<String, List<Map>> data = new HashMap<>();
        data.put("volList", tData);
        data.put("yesVolList", preTData);
        return R.ok(data);
    }

    /**
     * 统计在当前时间下（精确到分钟），股票在各个涨跌区间的数量
     *
     * @return 响应数据格式：
     * {
     * "code": 1,
     * "data": {
     * "time": "2021-12-31 14:58:00",
     * "infos": [
     * {
     * "count": 17,
     * "title": "-3~0%"
     * };...
     * }
     * }
     */
    @Override
    public R<Map> getStockUpdown() {
        //获取当前时间
        String avlDate = DateTimeUtil.getLastDateString4Stock(DateTime.now());
        //TODO 后续删除
        avlDate = "2022-01-06 09:55:00";
        //2.查询
        List<Map> maps = stockRtInfoMapper.getStockUpdown(avlDate);
        //获取去股票涨幅区间的集合
        List<String> upDownRange = stockInfoConfig.getUpDownRange();
        //将list集合下的字符串映射成Map对象
        //第一种lambda表达式
//        List<Map> orderMap = upDownRange.stream().map(key -> {
//            Optional<Map> title = maps.stream().filter(map -> key.equals(map.get("title"))).findFirst();
//            //判断对应map是否存在
//            Map tmp = null;
//            if (title.isPresent()) {
//                tmp = title.get();
//            } else {
//                tmp = new HashMap();
//                tmp.put("title", key);
//                tmp.put("count", 0);
//            }
//            return tmp;
//        }).collect(Collectors.toList());
        //第二种增强for循环
        ArrayList<Map> orderMap = new ArrayList<>();
        for (String title : upDownRange) {
            Map tmp =null;
            for (Map map : maps) {
                if (title.equals(map.get("title"))) {
                    tmp=map;
                }
            }
            if (tmp==null) {
                tmp=new HashMap();
                tmp.put("title",title);
                tmp.put("count",0);
            }
            orderMap.add(tmp);
        }
        //3.响应数据
        HashMap<String, Object> data = new HashMap<>();
        data.put("time",avlDate);
        data.put("infos",orderMap);
        return R.ok(data);
    }
    /**
     *个股分时行情
     * 查询单个个股的分时行情数据，查询时间周期是T日开盘到当前时间
     * @param code 个股编码
     * @return
     * 返回数据格式：
     * {
     *     "code": 1,
     *     "data": [
     *         {
     *             "date": "202112310925",//当前时间，精确到分钟
     *             "tradeAmt": 63263,//当前交易量
     *             "code": "000021",//股票编码
     *             "lowPrice": 15.85,//最低价格
     *             "preClosePrice": 15.85,//前收盘价格
     *             "name": "深科技",//股票名称
     *             "highPrice": 15.85,//最高价格
     *             "openPrice": 15.85,//开盘价
     *             "tradeVol": 1002718.55,//交易金额
     *             "tradePrice": 15.85//当前价格（最新价格）
     *         },....
     *  }
     */
    @Override
    public R<List<InnerRtTimeDomian>> getStockScreenTime(String code) {
        String tDate = DateTimeUtil.getLastDateString4Stock(DateTime.now());
        tDate="2021-12-30 09:32:55";
          List<InnerRtTimeDomian> infos= stockRtInfoMapper.getStockScreenTime(code,tDate);
        return R.ok(infos);
    }
    /**
     *单个个股日K数据查询 ，可以根据时间区间查询数日的K线数据
     *默认查询历史20天的数据；
     * @param code 个股编码
     * @return
     * 响应数据
     *
     */
    @Override
    public R<List<InnerRtTimeDomian>> getStockScreenDay(String code) {
        //获取当前日期前推20天
        Date tDate = DateTime.now().minusDays(20).toDate();
        //查询指定的股票在指定的日期范围内每天的股票统计数据
        List<InnerRtTimeDomian>  infos=stockRtInfoMapper.getStockScreenDay(code,tDate);
        return R.ok(infos);
    }
}
